#ifndef _MDEBUG_H_
#define _MDEBUG_H_

#include "../lua-5.1/lobject.h"
#include "../lua-5.1/lstate.h"

#include <stdio.h>

#include <windows.h>

extern char _md_log_buf[4096];
extern FILE* _md_log_f;

#define PRINT_DEBUG_LOG(fmt, ...) { \
	memset(_md_log_buf, 0, sizeof(_md_log_buf)); \
	sprintf(_md_log_buf, fmt, ##__VA_ARGS__); \
	OutputDebugString(_md_log_buf); \
    if(_md_log_f) {fprintf(_md_log_f, fmt, ##__VA_ARGS__);} \
}

#define PRINT_DEBUG_LOG_N(fmt, ...) PRINT_DEBUG_LOG(fmt "\n", ##__VA_ARGS__)

int init_mdebug();
int un_init_mdebug();

int MD_DUMP_LUA_OBJ(TValue* o, int deepth);
void MD_SHOW_STACK(lua_State* L);


int md_print_g_strt(lua_State* L);
int md_print_g_tmname(lua_State* L);
int md_print_g_rootgc(lua_State* L);
int md_print_ci(lua_State* L);

char* get_func_name_by_addr(void* addr);

#define MD_DEBUG_ALL(L) \
    PRINT_DEBUG_LOG_N("--==~~##$$@@!!- START -!!@@$$##~~==--"); \
    init_mdebug(); \
    MD_SHOW_STACK(L); \
    PRINT_DEBUG_LOG_N("L->l_gt"); \
    MD_DUMP_LUA_OBJ(&L->l_gt, -1); \
    PRINT_DEBUG_LOG_N("G->l_registry"); \
    MD_DUMP_LUA_OBJ(&L->l_G->l_registry, -1); \
    md_print_g_strt(L); \
    md_print_g_tmname(L); \
    md_print_g_rootgc(L); \
    PRINT_DEBUG_LOG_N("--==~~##$$@@!!- END -!!@@$$##~~==--\n"); \
    un_init_mdebug();

#define MD_DEBUG_ALL_F(L, memo, log_file_name) \
    _md_log_f = fopen("_md_" log_file_name, "w"); \
    PRINT_DEBUG_LOG_N(memo); \
    PRINT_DEBUG_LOG_N("--==~~##$$@@!!- START -!!@@$$##~~==--"); \
    init_mdebug(); \
    MD_SHOW_STACK(L); \
    PRINT_DEBUG_LOG_N("L->l_gt"); \
    MD_DUMP_LUA_OBJ(&L->l_gt, -1); \
    PRINT_DEBUG_LOG_N("G->l_registry"); \
    MD_DUMP_LUA_OBJ(&L->l_G->l_registry, -1); \
    md_print_g_strt(L); \
    md_print_g_tmname(L); \
    md_print_g_rootgc(L); \
    md_print_ci(L); \
    PRINT_DEBUG_LOG_N("--==~~##$$@@!!- END -!!@@$$##~~==--\n"); \
    un_init_mdebug(); \
    fclose(_md_log_f); _md_log_f = NULL;

#endif